#include "usk_event_admin_impl.h"

#include "Poco/Delegate.h"
#include "cppmicroservices/em/EventHandler.hpp"
#include "usk/core/usk_core.h"


namespace usk::core {

    USKEventAdminImpl::USKEventAdminImpl(OSGI *osgi) {
        osgi_ = osgi;
        event_ += Poco::delegate(osgi_, &OSGI::OnEvent);
        topic_ldap_filter_ = std::make_shared<USKCachedTopicFilter>();
    }

    USKEventAdminImpl::~USKEventAdminImpl() { event_ -= Poco::delegate(osgi_, &OSGI::OnEvent); }

    void USKEventAdminImpl::PostEvent(cppmicroservices::service::em::Event const &evt) noexcept {
        auto references = GetMatchedEventHandlersReference(evt);
        if (references.empty()) {
            return;
        }
        EventTaskers *taskers = new EventTaskers();
        taskers->event_handlers = std::move(references);
        auto result = event_.notifyAsync(taskers, const_cast<Event &>(evt));
        result.wait();
    }

    void USKEventAdminImpl::SendEvent(cppmicroservices::service::em::Event const &evt) noexcept {
        auto references = GetMatchedEventHandlersReference(evt);
        if (references.empty()) {
            return;
        }
        EventTaskers *taskers = new EventTaskers();
        taskers->event_handlers = std::move(references);
        event_.notify(taskers, const_cast<Event &>(evt));
    }

    std::vector<cppmicroservices::ServiceReference<EventHandler>>
    USKEventAdminImpl::GetMatchedEventHandlersReference(Event const &evt) {
        if (nullptr == osgi_ || nullptr == topic_ldap_filter_) {
            return std::vector<cppmicroservices::ServiceReference<EventHandler>>();
        }
        auto bundle_context = osgi_->GetBundleContext();
        const auto filter = topic_ldap_filter_->CreateTopicFilter(evt.GetTopic());
        return bundle_context.GetServiceReferences<EventHandler>(filter->ToString());
    }

} // namespace usk::core
